package com.cold.demo.webflux.controller;

import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@RestController
public class DemoController {

    private Logger log = LoggerFactory.getLogger(DemoController.class);

    //======================================普通模式-开始=========================================================================
    @GetMapping({"/", "/index"})
    public Object index(String p) {
        System.out.println(p);
        Map<String, String> map = new HashMap<>();
        map.put("key", "p=" + p + System.currentTimeMillis());
        return map;
    }

    @PostMapping("/body")
    public Object body(@RequestBody Map<Object, Object> bodyInfo) {
        System.out.println(bodyInfo);
        Map<String, Object> map = new HashMap<>();
        map.put("bodyInfo", bodyInfo);
        map.put("key", bodyInfo + "=======" + System.currentTimeMillis());
        return map;
    }
    //======================================普通模式-结束=========================================================================

    //======================================Mono-开始=========================================================================

    @GetMapping(value = {"/mono", "/mono/index"}, produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Mono<String> indexMono(String p) {
        return Mono.just("Hello WebFlux!").publishOn(Schedulers.elastic()).map(s -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return s;
        });
    }


    @PostMapping("/mono/body")
    public Mono<Map<String, Object>> bodyMono(@RequestBody Map<Object, Object> bodyInfo) {
        System.out.println(bodyInfo);
        Map<String, Object> map = new HashMap<>();
        map.put("key", bodyInfo + "=======" + System.currentTimeMillis());
        map.put("bodyInfo", bodyInfo);
        return Mono.just(map);
    }

    @GetMapping(value = "/bodyFlux", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<String> bodyFlux(@RequestBody Flux<Part> parts) {
        return parts.map(part -> part instanceof FilePart
                ? part.name() + ":" + ((FilePart) part).filename()
                : part.name())
                .collect(Collectors.joining(",", "[", "]"));
    }
    //======================================Mono-结束=========================================================================


    //======================================Flux-开始=========================================================================

    /**
     * 如果不是application/stream json 則呼叫端無法滾動得到結果，將一直阻塞等待資料流結束或超時。
     */
    @GetMapping(value = "/stream", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Flux<String> stream() {
        return Flux.interval(Duration.ofMillis(500))
                .map(l -> System.currentTimeMillis() + "哈哈哈\n")
                .log();
    }

    @GetMapping(value = "/stream2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> stream2() {
        return Flux.interval(Duration.ofMillis(500)).map(l -> System.currentTimeMillis() + "哈哈哈\n").log();
    }

    @GetMapping(value = "/stream3", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Long> stream3() {
        return Flux.interval(Duration.ofMillis(1000));
    }

    //======================================Flux-结束=========================================================================

}
